// Utility functions used throughout the mod

#include "g_local.h"
#include "bots_local.h"


char	lastmsg[1024];


void bots_Coordinates ( gentity_t *ent )
{
	char		ls_coord[1024];
	gclient_t	*client;
	int			clientNum;
	
	if (!ent->client)
		return;

	Com_sprintf(ls_coord, sizeof(ls_coord), "{%5.6f, %5.6f, %5.6f}", ent->client->ps.origin[0], ent->client->ps.origin[1], ent->client->ps.origin[2]);

	client = ent->client;
	clientNum = client - level.clients;

	BOTS_cp_console(clientNum, ls_coord);
}

/////////////////////////////////////////////////////////////////
// BOTS_cp_console
//
// Centerprint to the client and dump the data to the console.
// Used for important data that the client may want to referrence later.
//
#define SPAM_DEBOUNCE_DELAY		350
void BOTS_cp_console(int clientNum, char* text)
{
	// Broadcasted msg are just broadcasted (unfiltered)
	if (clientNum == -1)
		trap_SendServerCommand( -1, va("cp \"%s\n\"", text));
	else
	{
		gentity_t* ent = g_entities + clientNum;
		
		
		if ((ent->client) && (!ent->client->pers.isbot) && (level.time > ent->client->iSpamDebounce)) {
			ent->client->iSpamDebounce = level.time + SPAM_DEBOUNCE_DELAY;
			trap_SendServerCommand( clientNum, va("cp \"%s\n\"", text));
		}
	}
}

void BOTS_console(int clientNum, char* text)
{
	if (clientNum == -1)
		trap_SendServerCommand( -1, va("print \"%s\n\"", text));
	else
	{
		gentity_t* ent = g_entities + clientNum;
		
		
		if ((ent->client) && (!ent->client->pers.isbot) && (level.time > ent->client->iSpamDebounce)) {
			ent->client->iSpamDebounce = level.time + SPAM_DEBOUNCE_DELAY;
			trap_SendServerCommand( clientNum, va("print \"%s\n\"", text));
		}
	}
}

/////////////////////////////////////////////////////////////////
// findradius - totally ripped from:
// http://quakestyle.telefragged.com/quake3/tutorial10.htm
// (NOBODY): Code helper function
//
gentity_t *findradius (gentity_t *retval, vec3_t origin, float rad)
{
	vec3_t  eorg;
	int             j;

	if (!retval)
		retval = g_entities;
	else
		retval++;

	for (; retval < &g_entities[level.num_entities]; retval++)
	{
		if (!retval->inuse)
			continue;
		for (j=0; j<3; j++)
			eorg[j] = origin[j] - (retval->s.pos.trBase[j] + (retval->r.mins[j] + retval->r.maxs[j])*0.5);
		if (VectorLength(eorg) > rad)
			continue;
		return retval;
	}
	return NULL;
}

// tbp: only returns clients. dunno how many cycles were saved by that simple modification ;)
gentity_t *findradiusCLIENT(gentity_t *retval, vec3_t origin, float rad)
{
	vec3_t  eorg;
	int             j;

	if (!retval)
		retval = g_entities;
	else
		retval++;

	for (; retval < &g_entities[level.maxclients]; retval++)
	{
		if (!retval->inuse)
			continue;
		for (j=0; j<3; j++)
			eorg[j] = origin[j] - (retval->s.pos.trBase[j] + (retval->r.mins[j] + retval->r.maxs[j])*0.5);
		if (VectorLength(eorg) > rad)
			continue;
		return retval;
	}
	return NULL;
}
/////////////////////////////////////////////////////////////////
// visible - totally ripped from:
// http://quakestyle.telefragged.com/quake3/tutorial11.htm
// (NOBODY): Code helper function
//
qboolean visible( gentity_t *ent1, gentity_t *ent2 ) 
{
    trace_t	trace;
    trap_Trace (&trace, ent1->s.pos.trBase, NULL, NULL, ent2->s.pos.trBase, ent1->s.number, MASK_SHOT );
    if ( trace.contents & CONTENTS_SOLID )
		return qfalse;

    return qtrue;
}

/////////////////////////////////////////////
//
// BOTS_angle_bisect
//
// This function will calculate the vector that splits 2 vectors at a given angle.
// This function assumes a counter clockwise rotation.
//
// IN:
//		vec3_t forward	- vector1
//		vec3_t right	- vector2
//		vec3_t up		- vector3
//		float angle		- angle between right and new vector
//
// OUT:
//		vec3_t out		- newly calculated vector
//
void BOTS_vectorFromAngle(vec3_t forward, vec3_t right, vec3_t up, float angle, vec3_t out)
{
	// this is right...
	vec3_t tmp1;
	vec3_t tmp2;

	// first component
	VectorScale(right, cos(angle*(M_PI*2 / 360)), tmp1);

	// second component
	CrossProduct(up, right, tmp2);
	VectorScale(tmp2, sin(angle*(M_PI*2 / 360)), tmp2);

	VectorAdd(tmp1, tmp2, out);
}

void BOTS_remove_poison(gentity_t* ent)
{
	int i;

	if (!ent->client)
		return;
	if (ent->bots_class != BOTS_NURSE)
		return;

	for (i = 0; i < level.num_entities; i++)
	{
		gentity_t* health = g_entities + i;

		if (!health->item)
			continue;
		if (health->item->giType != IT_HEALTH)
			continue;

		if (!health->poisoner)
			continue;
		if (health->poisoner != ent)
			continue;
		
		health->poisoner = NULL;
		health->last_poisoner = NULL;
	}
}
